package xyz.liuz.edb.heart;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import io.netty.util.CharsetUtil;
import org.json.JSONObject;
import xyz.liuz.edb.heart.protocol.CoorMessageProtocol;

public class HeartServerHandler extends SimpleChannelInboundHandler<CoorMessageProtocol> {
    private int heartCounter = 0;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, CoorMessageProtocol msg) throws Exception {
        heartCounter = 0;

        //解析消息
        int messageType = msg.getMessageType();
        String messageString = new String(msg.getMessage(), CharsetUtil.UTF_8);
        System.out.println("已缓存的节点信息:"+HeartServer.channelMap.toString());
        if (messageType == 1){
            System.out.println("收到远程客户端（"+ctx.channel().remoteAddress()+")心跳信息"+messageString);
            //响应心跳
            CoorMessageProtocol messageProtocol = new CoorMessageProtocol();
            messageProtocol.setMessageType(1);
            byte[] pang = "pang".getBytes(CharsetUtil.UTF_8);
            messageProtocol.setMessageLength(pang.length);
            messageProtocol.setMessage(pang);
            ctx.writeAndFlush(messageProtocol);
            //缓存客户端channel
            JSONObject msgJson = new JSONObject(messageString);
            String nodeId = msgJson.getString("nodeId");//节点ID
            String agentHost = msgJson.getString("agentHost");//节点IP
            if(HeartServer.channelMap.containsKey(agentHost + nodeId)){
                System.out.println("存在该节点");
                return;
            }
            //不存在
            HeartServer.channelMap.put(agentHost+nodeId,ctx.channel());

            //在channel中添加节点ID和节点IP属性
            AttributeKey<String> nodeIdAttrKey = AttributeKey.valueOf("NODE_ID");
            AttributeKey<String> nodeIpAttrKey = AttributeKey.valueOf("NODE_IP");
            ctx.channel().attr(nodeIdAttrKey).set(nodeId);;
            ctx.channel().attr(nodeIpAttrKey).set(agentHost);

            return;
        }
        if (messageType == 3){
            System.out.println("F5("+ctx.channel().remoteAddress() +")心跳信息:"+messageString);
            CoorMessageProtocol messageProtocol = new CoorMessageProtocol();
            messageProtocol.setMessageType(3);
            byte[] pang = "EDBHEARTBEAT".getBytes(CharsetUtil.UTF_8);
            messageProtocol.setMessageLength(pang.length);
            messageProtocol.setMessage(pang);
            ctx.writeAndFlush(messageProtocol);

            return;
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("远程客户端："+ctx.channel().remoteAddress().toString() +" 已激活！");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        AttributeKey<String> nodeIdAttrKey = AttributeKey.valueOf("NODE_ID");
        String nodeId = ctx.channel().attr(nodeIdAttrKey).get();
        System.out.println("离线的节点ID：" + nodeId);
        AttributeKey<String> nodeIpAttrKey = AttributeKey.valueOf("NODE_IP");
        String nodeIp = ctx.channel().attr(nodeIpAttrKey).get();
        System.out.println("离线的节点IP：" + nodeIp);
        //在缓存中出去该客户端channel
        if(HeartServer.channelMap.containsKey(nodeIp+nodeId)){
            HeartServer.channelMap.remove(nodeIp+nodeId);
        }

        super.channelInactive(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent){
            IdleStateEvent event = (IdleStateEvent) evt;
            //如果为读空闲
            if(event.state().equals(IdleState.READER_IDLE)){
                if(heartCounter >= 3){
                    ctx.channel().close().sync();
                    System.out.println("已与："+ ctx.channel().remoteAddress()+"断开连接");
                }else{
                    heartCounter++;
                    System.out.println(ctx.channel().remoteAddress() + "已经空闲 "+heartCounter+" 次");
                }

            }

        }


        super.userEventTriggered(ctx, evt);
    }
}
